<template>
	<view class="float-ball-wrapper" id="floatBallWrapper" :style="[floatBallWrapperStyle]">
		<div v-if="dragable" class="float-ball" :style="{ background: background,color:ballTextColor,fontSize:ballTextSize }" @touchstart.stop="touchstart" @touchmove.stop="touchmove" @touchend.stop="touchend">
			<div class="slots" :class="[slotsDirectionData]">
				<slot />
			</div>
			<!-- {{ballText}} -->
			 <view style="display: flex;align-items: center; font-size: 22rpx;">
				<image
				style="width: 48rpx; height: 48rpx;"
					src="../static/images/jia.png"
					mode="scaleToFill"
				/>
				<view style="margin-left: 20rpx;">
					<view>添加</view>
					<view>楼栋</view>
				</view>
			 </view>
		</div>
		<div v-else class="float-ball">
			<div class="slots" :class="[slotsDirectionData]">
				<slot />
			</div>
		</div>
	</view>
</template>

<script>
export default {
	name: 'duiFloatBall',
	emits: ['touchFunc'],
	props: {
		dragable: {
			type: Boolean,
			default: true
		},
		ballWidth:{
			type:String,
			default:"100rpx"
		},
		ballText:String,
		ballTextColor:{
			type:String,
			default:"#fff"
		},
		ballTextSize:{
			type:String,
			default:"28rpx"
		},
		background: String,
		position: {
			type: Object,
			default: function () {
				return {
					left: '100%',
					top: '70%'
				};
			}
		},
		immediateIndent: {
			type: Boolean,
			default: true
		},
		needNearEdge: {
			type: Boolean,
			default: true
		},
		nearEdgeDirection: String,
		nearEdgeTransition: {
			type: String,
			default: 'all ease 0.3s'
		},
		nearEdgeIndent: {
			type: Boolean,
			default: true
		},
		nearEdgeIndentDelay: {
			type: Number,
			default: 1000
		},
		nearEdgeIndentDistance: {
			type: Number,
			default: 30
		},
		slotsDirection: {
			type: String,
			default: ''
		}
	},

	data() {
		return {
			slotsDirectionData: 'right',
			touchType: 0,
			starX: 0,
			starY: 0,
			floatBallPositionLeft: 0,
			floatBallPositionTop: 0,
			floatBallWidth: 0,
			floatBallHeight: 0,
			windowWidth: 0,
			windowHeight: 0,
			floatBallWrapperStyle: {
				left: 0,
				top: 0,
				transform:'',
			},
			left: 0,
			top: 0,
			indentTimer: null,
			indentNearEdgeTimer: null,
			totalTranslateX: 0,
			totalTranslateY: 0
		};
	},
	methods: {
		touchstart(e) {
			const starX = e.touches[0].clientX;
			const starY = e.touches[0].clientY;
			e.preventDefault();
			this.clearAllTimeout();
			this.floatBallWrapperStyle.transition = 'none';
			this.touchType = 0;
			this.starX = starX;
			this.starY = starY;
		},

		touchmove(e) {
			const clientX = e.touches[0].clientX;
			const clientY = e.touches[0].clientY;
			const moveXDistance = clientX - this.starX;
			const moveYDistance = clientY - this.starY;
			if (Math.abs(moveXDistance) > 10 || Math.abs(moveYDistance) > 10) {
				this.touchType = 1;
			}
			this.validMove(moveXDistance, moveYDistance);
		},

		touchend(e) {
			const clientX = e.changedTouches[0].clientX;
			const clientY = e.changedTouches[0].clientY;
			const moveXDistance = clientX - this.starX;
			const moveYDistance = clientY - this.starY;
			const { translateX, translateY } = this.calcTranslateXY(moveXDistance, moveYDistance);
			if (this.touchType === 0) {
				this.touchCallBackFunc();
			}
			this.totalTranslateX = translateX;
			this.totalTranslateY = translateY;
			if(this.needNearEdge){
				this.getFloatBallLatestRect().then(rect=>{
					let minKey = '';
					let obj = {
						left:rect.left,
						top:rect.top,
						right:this.windowWidth - rect.left - this.floatBallWidth,
						bottom:this.windowHeight - rect.top - this.floatBallHeight,
					}
					let translateX = this.totalTranslateX;
					let translateY = this.totalTranslateY;
					if (this.nearEdgeDirection) {
						minKey = this.nearEdgeDirection;
					} else {
						let min = Math.min();
						for (const key in obj) {
							const val = parseFloat(obj[key]);
							if (val < min) {
								min = val;
								minKey = key;
							}
						}
					}
					
					this.setNearEdgeAndIndent(minKey);
					
					if (this.nearEdgeIndent) {
						if (this.nearEdgeIndentDelay !== 0) {
							clearTimeout(this.indentNearEdgeTimer);
							this.indentNearEdgeTimer = setTimeout(() => {
								this.setNearEdgeAndIndent(minKey,this.nearEdgeIndentDistance);
							}, this.nearEdgeIndentDelay);
						} else {
							this.setNearEdgeAndIndent(minKey,this.nearEdgeIndentDistance);
						}
					}
					
					this.setSlotsDirection(minKey);
				})
			}
		},
		
		touchCallBackFunc(){
			this.getFloatBallLatestRect().then(rect=>{
				const {right,bottom,top,left} = rect;
				let iSNearEdge = false;
				if(Math.ceil(right) >= this.windowWidth || Math.floor(top) <= 0){
					iSNearEdge = true;
				}
				if(Math.ceil(bottom) >= this.windowHeight || Math.floor(left) <= 0){
					iSNearEdge = true;
				}
				this.$emit('touchFunc',{iSNearEdge});
			})
		},

		validMove(moveXDistance, moveYDistance) {
			const { translateX, translateY } = this.calcTranslateXY(moveXDistance, moveYDistance);
			this.floatBallWrapperStyle.transform = `translate(${translateX}px,${translateY}px)`;
		},

		calcTranslateXY(moveXDistance, moveYDistance) {
			let translateX = this.totalTranslateX + moveXDistance;
			let translateY = this.totalTranslateY + moveYDistance;
			if (this.floatBallPositionLeft + translateX < 0) {
				translateX = -this.floatBallPositionLeft;
			}
			if (this.floatBallPositionLeft + translateX + this.floatBallWidth > this.windowWidth) {
				translateX = this.windowWidth - this.floatBallWidth - this.floatBallPositionLeft;
			}
			if (this.floatBallPositionTop + translateY < 0) {
				translateY = -this.floatBallPositionTop;
			}
			if (this.floatBallPositionTop + translateY + this.floatBallHeight > this.windowHeight) {
				translateY = this.windowHeight - this.floatBallHeight - this.floatBallPositionTop;
			}
			return {
				translateX,
				translateY
			};
		},

		setNearEdgeAndIndent(minKey, nearEdgeIndentDistance = 0) {
			let translateX = this.totalTranslateX;
			let translateY = this.totalTranslateY;
			if(nearEdgeIndentDistance < 0){
				nearEdgeIndentDistance = 0;
			}else if(nearEdgeIndentDistance <= 1){
				nearEdgeIndentDistance = this.floatBallWidth * nearEdgeIndentDistance;
			}
			switch (minKey) {
				case 'left':
					translateX = -this.floatBallPositionLeft - nearEdgeIndentDistance;
					break;
				case 'right':
					translateX = this.windowWidth - this.floatBallWidth - this.floatBallPositionLeft + nearEdgeIndentDistance;
					break;
				case 'top':
					translateY = -this.floatBallPositionTop - nearEdgeIndentDistance;
					break;
				case 'bottom':
					translateY = this.windowHeight - this.floatBallHeight - this.floatBallPositionTop + nearEdgeIndentDistance;
					break;
			}
			if (this.nearEdgeTransition) {
				this.floatBallWrapperStyle.transition = this.nearEdgeTransition;
			}
			this.totalTranslateX = translateX;
			this.totalTranslateY = translateY;
			this.floatBallWrapperStyle.transform = `translate(${translateX}px,${translateY}px)`;
		},

		setSlotsDirection(minKey) {
			let slotsDirection = '';
			switch (minKey) {
				case 'left':
					slotsDirection = 'right';
					break;
				case 'right':
					slotsDirection = 'left';
					break;
				case 'top':
					slotsDirection = 'bottom';
					break;
				case 'bottom':
					slotsDirection = 'top';
					break;
			}
			if (!this.slotsDirection) {
				this.slotsDirectionData = slotsDirection;
			} else {
				this.slotsDirectionData = this.slotsDirection;
			}
		},

		clearAllTimeout() {
			clearTimeout(this.indentTimer);
			clearTimeout(this.indentNearEdgeTimer);
		},

		setIndent(minkey) {
			this.clearAllTimeout();
			this.indentTimer = setTimeout(() => {
				this.setNearEdgeAndIndent(minkey,this.nearEdgeIndentDistance);
			}, this.nearEdgeIndentDelay);
		},

		setFloatBallWH() {
			// #ifndef MP-ALIPAY
			const query = uni.createSelectorQuery().in(this);
			query
				.select('#floatBallWrapper')
				.boundingClientRect((rect) => {
					this.floatBallWidth = rect.width;
					this.floatBallHeight = rect.height;
					this.floatBallPositionLeft = rect.left;
					this.floatBallPositionTop = rect.top;
					this.initSet();
				})
				.exec();
			// #endif
			// #ifdef MP-ALIPAY
			my.createSelectorQuery()
				.select('#floatBallWrapper')
				.boundingClientRect()
				.exec((ret) => {
					this.floatBallWidth = ret[0].width;
					this.floatBallHeight = ret[0].height;
					this.floatBallPositionLeft = ret[0].left;
					this.floatBallPositionTop = ret[0].top;
					this.initSet();
				});
			// #endif
		},
		
		getFloatBallLatestRect(){
			return new Promise((resolve,rejct)=>{
				// #ifndef MP-ALIPAY
				const query = uni.createSelectorQuery().in(this);
				query
					.select('#floatBallWrapper')
					.boundingClientRect((rect) => {
						resolve(rect);
					})
					.exec();
				// #endif
				// #ifdef MP-ALIPAY
				my.createSelectorQuery()
					.select('#floatBallWrapper')
					.boundingClientRect()
					.exec((ret) => {
						resolve(ret[0]);
					});
				// #endif
			})
		},

		setWindowWH() {
			let windowInfo = {};
			// #ifdef H5 || MP-WEIXIN || APP
			windowInfo = uni.getWindowInfo();
			// #endif

			// #ifdef MP-QQ
			windowInfo = qq.getSystemInfoSync();
			// #endif

			// #ifdef MP-ALIPAY
			windowInfo = my.getSystemInfoSync();
			// #endif

			// #ifdef MP-TOUTIAO || MP-LARK
			windowInfo = tt.getSystemInfoSync();
			// #endif

			// #ifdef MP-KUAISHOU
			windowInfo = ks.getSystemInfoSync();
			// #endif

			// #ifdef MP-BAIDU
			windowInfo = swan.getSystemInfoSync();
			// #endif

			// #ifdef MP-JD
			windowInfo = jd.getSystemInfoSync();
			// #endif

			// #ifdef MP-360
			const qhSystemInfo = qh.getSystemInfoSync();
			windowInfo.windowWidth = qhSystemInfo.screenWidth;
			windowInfo.windowHeight = qhSystemInfo.screenHeight;
			// #endif

			this.windowWidth = windowInfo.windowWidth;
			this.windowHeight = windowInfo.windowHeight;
		},

		initSet() {
			let minkey = 'top';
			let translateX = '';
			let translateY = '';
			if (this.position.left == '100%') {
				minkey = 'right';
				translateX = -this.floatBallWidth;
				this.floatBallWrapperStyle.transform = `translateX(${translateX}px)`;
				this.totalTranslateX = translateX;
			} else {
				minkey = 'left';
			}
			if (this.position.top == '100%') {
				minkey = 'bottom';
				translateY = -this.floatBallHeight;
				this.floatBallWrapperStyle.top = this.windowHeight+'px';
				this.floatBallWrapperStyle.transform = `translateY(${translateY}px)`;
				this.totalTranslateY = translateY;
				this.floatBallPositionTop = this.windowHeight;
			}
			this.setSlotsDirection(minkey);
			if (this.immediateIndent && this.nearEdgeIndent) {
				this.setIndent(minkey);
			}
		}
	},

	created() {
		this.floatBallWrapperStyle.top = this.position.top;
		this.floatBallWrapperStyle.left = this.position.left;
		if (typeof this.nearEdgeIndentDistance != 'number') {
			console.error('nearEdgeIndentDistance值必须为number类型');
		}
	},

	mounted() {
		this.setWindowWH();
		this.setFloatBallWH();
	},

	beforeDestroy() {
		this.clearAllTimeout();
	}
};
</script>

<style lang="scss">
.float-ball-wrapper {
	position: fixed;
	width: 132rpx;
	height: 72rpx;
	background: linear-gradient( 180deg, #FF870A 0%, #FE4F04 100%);
	border-radius: 200rpx 0rpx 0rpx 200rpx;
	z-index: 997;
	.float-ball {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 100%;
		height: 100%;
		border-radius: 50%;
		// background: #00aa7f;

		.slots {
			position: absolute;
			width: fit-content;
			&.right {
				left: calc(100% + 10px);
			}

			&.left {
				right: calc(100% + 10px);
			}

			&.top {
				bottom: calc(100% + 10px);
			}

			&.bottom {
				top: calc(100% + 10px);
			}
		}
	}
}
</style>
